package parser.nodes;

import codegen.AbstractDescr;
import codegen.CodeGen;
import codegen.ParamDescr;
import codegen.ProcedureDescr;
import java.util.List;
import scanner.Token;

// ProcedureCall = ident '(' [ActualParameters] ')'
public class ProcedureCallNode extends Node {
    Token identifier;
    ActualParametersNode parameters;

    public ProcedureCallNode(Token identifier, ActualParametersNode parameters) {
        this.identifier = identifier;
        this.parameters = parameters;
    }
    
    public ProcedureCallNode(Token identifier) {
        this(identifier, null);
    }
    
    @Override
    public void print() {
        p("ProcedureCall:");
        indent();
        p(identifier);
        p("(");
        parameters.print();
        p(")");
        unindent();
    }

	@Override
	public void abstractPrint() {
		p("PROCCALL");
		indent();
		p(identifier);
		parameters.abstractPrint();
		unindent();
	}

	@Override
	public void compile(CodeGen c) throws CompileError {
		AbstractDescr descr = c.findDescr(identifier.toString());

		if (descr instanceof ProcedureDescr) {
			c.outstr("//Parameter auf Stack legen");
			ProcedureDescr proc = (ProcedureDescr) descr;
			
			List<ParamDescr> descrs = proc.getParams();
			if (parameters != null) {
				c.outstr("INIT, " + proc.getSize());
				List<ExpressionNode> exprs = parameters.getExpressions();
				for(int i = descrs.size()-1; i >= 0; --i) {
					if (descrs.get(i).isVar())
						exprs.get(i).removeCont();


					exprs.get(i).compile(c);

					int size = descrs.get(i).getSize();
					c.outstr("GETSP");
					c.outstr("ASSIGN, " + size);

					c.outstr("GETSP");
					c.outstr("PUSHI, " + size);
					c.outstr("ADD");
					c.outstr("SETSP");
				}
			}
			
			c.outstr("CALL, " + proc.getStart());
			
			//Parameter abräumen
			c.outstr("//Parameter abräumen");
			if (parameters != null) {
				c.outstr("GETSP");
				c.outstr("PUSHI, " + proc.getSize());
				c.outstr("SUB");
				c.outstr("SETSP");
				c.outstr("REDUCE, " + proc.getSize());
			}
		} else {
			throw new CompileError("Trying to call unknown procedure '" + identifier.toString() + "'");
		}
	}
}
